/*
 * ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is the KBUS Lightweight Linux-kernel mediated
 * message system
 *
 * The Initial Developer of the Original Code is Kynesim, Cambridge UK.
 * Portions created by the Initial Developer are Copyright (C) 2010
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *   Kynesim, Cambridge UK
 *   Tony Ibbs <tibs@tonyibbs.co.uk>
 *
 * ***** END LICENSE BLOCK *****
 */

#ifndef _LIMPET_H_INCLUDED_
#define _LIMPET_H_INCLUDED_

#ifdef __cplusplus
extern "C" {
#endif

// NOTE that the middle portion of this file is autogenerated from limpet.c
// so that the function header comments and function prototypes may be
// automatically kept in-step. This allows me to treat the C file as the main
// specification of the functions it defines, and also to keep C header
// comments in the C file, which I find easier when keeping the comments
// correct as the code is edited.
//
// The Python script extract_hdrs.py is used to perform this autogeneration.
// It should transfer any C function marked as 'extern' and with a header
// comment (of the '/*...*...*/' form).

/*
 * The information needed to transform KBUS messages for Limpets:
 *
 * 1. after reading from KBUS and before writing to the other Limpet
 * 2. after receiving from the other Limpet and before writing to KBUS
 *
 * This is created by a call to kbus_limpet_new_context(), and freed
 * by a call to kbus_limpet_free_context().
 */
struct kbus_limpet_context;
typedef struct kbus_limpet_context kbus_limpet_context_t;


/*
 * Length of an array sufficient to hold the parts of a message header that
 * we need to send to/receive from the other Limpet.
 */
#define KBUS_SERIALISED_HDR_LEN 16

/*
 * Limpet specific messages.
 *
 * The "RemoteError" message has an error number appended to its name.
 */
#define KBUS_MSG_NOT_SAME_KSOCK         "$.KBUS.Replier.NotSameKsock"
#define KBUS_MSG_REMOTE_ERROR_PREFIX    "$.KBUS.RemoteError."

// -------- TEXT AFTER THIS AUTOGENERATED - DO NOT EDIT --------
// Autogenerated by extract_hdrs.py on 2013-01-16 (Wed 16 Jan 2013) at 11:47

/*
 * Given a KBUS message, set the `result` array to its content, suitable for
 * sending across the network
 *
 * Ignores the message's name and data pointers.
 *
 * Thus we end up with::
 *
 *  result[0]  = msg->start_guard
 *  result[1]  = msg->id.network_id
 *  result[2]  = msg->id.serial_num
 *  result[3]  = msg->in_reply_to.network_id
 *  result[4]  = msg->in_reply_to.serial_num
 *  result[5]  = msg->to
 *  result[6]  = msg->from
 *  result[7]  = msg->orig_from.network_id
 *  result[8]  = msg->orig_from.local_id
 *  result[9]  = msg->final_to.network_id
 *  result[10] = msg->final_to.local_id
 *  result[11] = msg->extra
 *  result[12] = msg->flags
 *  result[13] = msg->name_len
 *  result[14] = msg->data_len
 *  result[15] = msg->end_guard
 */
extern void kbus_serialise_message_header(kbus_message_t *msg,
                                          uint32_t        result[KBUS_SERIALISED_HDR_LEN]);

/*
 * Given a serialised message header from the network, set the message's header
 *
 * Leaves the message's name and data pointers unset (NULL).
 */
extern void kbus_unserialise_message_header(uint32_t        serial[KBUS_SERIALISED_HDR_LEN],
                                            kbus_message_t *msg);

/*
 * Prepare for Limper handling on the given Ksock, and return a Limpet context.
 *
 * This function binds to the requested message name, sets up Replier Bind
 * Event messages, and requests only one copy of each message.
 *
 * - 'ksock' is the Ksock which is to this end of our Limpet. It must be open
 *   for read and write.
 * - 'network_id' is the network id which identifies this Limpet. It is set in
 *   message ids when we are forwarding a message to the other Limpet. It must
 *   be greater than zero.
 * - 'other_network_id' is the network if of the other Limpet. It must not be
 *   the same as our_network_id. It must be greater than zero.
 * - 'message_name' is the message name that this Limpet will bind to, and
 *   forward. This will normally be a wildcard, and defaults to "$.*". Other
 *   messages will treated as ignorable. A copy is taken of this string.
 * - if 'verbosity' is:
 *
 *   * 0, we are as silent as possible
 *   * 1, we announce ourselves, and output any error/warning messages
 *   * 2 (or higher), we output information about each message as it is
 *     processed.
 *
 * 'context' is the Limpet context, allocated by this function. Free it with
 * ksock_limpet_free_context() when it is no longer required.
 *
 * Returns 0 if all goes well, a negative number (``-errno``) for
 * failure (in particular, returns -EBADMSG if 'message_name' is NULL or too
 * short).
 */
extern int kbus_limpet_new_context(kbus_ksock_t              ksock,
                                   uint32_t                  network_id,
                                   uint32_t                  other_network_id,
                                   char                     *message_name,
                                   uint32_t                  verbosity,
                                   kbus_limpet_context_t   **context);

/*
 * Change the verbosity level for a Limpet context
 */
extern void kbus_limpet_set_verbosity(kbus_limpet_context_t *context,
                                      uint32_t               verbosity);

/*
 * Free a Kbus Limpet context that is no longer required.
 *
 * After freeing 'context', it will be set to a pointer to NULL.
 *
 * If 'context' is is already a pointer to NULL, this function does nothing.
 */
extern void kbus_limpet_free_context(kbus_limpet_context_t  **context);

/*
 * Given a message read from KBUS, amend it for sending to the other Limpet.
 *
 * Returns:
 *
 * * 0 if the message has successfully been amended, and should be sent to
 *   KBUS.
 * * 1 if the message is not of interest and should be ignored.
 * * A negative number (``-errno``) for failure.
 */
extern int kbus_limpet_amend_msg_from_kbus(kbus_limpet_context_t *context,
                                           kbus_message_t        *msg);

/*
 * Given a message read from the other Limpet, amend it for sending to KBUS.
 *
 * * 'context' describes the Limpet environment
 * * 'msg' is the message to be amended. It will be changed appropriately.
 *   Note that the message data will never be touched.
 * * 'error' will be NULL or an error message to be sent to the other Limpet.
 *   In the latter case, it is up to the caller to free it.
 *
 * Returns:
 *
 * * 0 if the message has successfully been amended, and should be sent to
 *   KBUS.
 * * 1 if the message is not of interest and should be ignored.
 * * 2 if an error occurred, and the 'error' message should be sent (back)
 *   to the other Limpet (in this case the original error should not be
 *   send to KBUS).
 * * A negative number (``-errno``) for failure.
 */
extern int kbus_limpet_amend_msg_to_kbus(kbus_limpet_context_t  *context,
                                         kbus_message_t      *msg,
                                         kbus_message_t     **error);

/*
 * Convert the data of a Replier Bind Event message to network order.
 *
 * Does not check the message name, so please only call it for
 * messages called "$.ReplierBindEvent" (KBUS_MSG_NAME_REPLIER_BIND_EVENT).
 */
extern void kbus_limpet_ReplierBindEvent_hton(kbus_message_t  *msg);

/*
 * Convert the data of a Replier Bind Event message to host order.
 *
 * Does not check the message name, so please only call it for
 * messages called "$.ReplierBindEvent" (KBUS_MSG_NAME_REPLIER_BIND_EVENT).
 */
extern void kbus_limpet_ReplierBindEvent_ntoh(kbus_message_t  *msg);

/*
 * If sending to our Ksock failed, maybe generate a message suitable for
 * sending back to the other Limpet.
 *
 * 'msg' is the message we tried to send, 'errnum' is the error returned
 * by KBUS when it tried to send the message.
 *
 * 'error' is the new error message. The caller is responsible for freeing
 * 'error'.
 *
 * An 'error' message will be generated if the original message was a Request,
 * and (at time of writing) not otherwise.
 *
 * Returns
 *
 * * 0 if all goes well (in which case 'error' is non-NULL).
 * * 1 if there is no need to send an error to the other Limpet, 'error' is
 *   NULL, and the event should be ignored.
 * * A negative number (``-errno``) for failure.
 */
extern int kbus_limpet_could_not_send_to_kbus_msg(kbus_limpet_context_t  *context,
                                                  kbus_message_t      *msg,
                                                  int                  errnum,
                                                  kbus_message_t     **error);
// -------- TEXT BEFORE THIS AUTOGENERATED - DO NOT EDIT --------

#ifdef __cplusplus
}
#endif

#endif /* _LIMPET_H_INCLUDED_ */

// Local Variables:
// tab-width: 8
// indent-tabs-mode: nil
// c-basic-offset: 2
// End:
// vim: set tabstop=8 shiftwidth=2 softtabstop=2 expandtab:
